/**
 * 
 */
package bancosys.tec.datadigester.input;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import jmine.tec.datadigester.DataDigesterMessages;
import jmine.tec.utils.io.IOUtils;
import bancosys.tec.datadigester.DataDigesterException;

/**
 * Given any inputStream, returns a inputStream that will return the same data, but supports the mark/reset methods. Streams created here
 * also override the default close() method, to avoid parsers to close it. After all operations are done with this inputStream, the method
 * doClose() must be called to free it's resources. This factory "knows" some InputStream implementations to avoid unnecessary creation of
 * temporary files (expensive, used only if needed).
 * 
 * @author lundberg
 */
public final class ResetableInputStreamFactory {

    /**
     * Constructor
     */
    private ResetableInputStreamFactory() {
    }

    /**
     * Creates an inputStream with the properties described on the class description.
     * 
     * @param in InputStream
     * @return HiddenCloseInputStream
     */
    public static InputStream createResetableInputStream(InputStream in) {
        if (in instanceof ByteArrayInputStream) {
            return in;
        } else if (in instanceof ResetableFileInputStream) {
            return new ResetableFileInputStream((ResetableFileInputStream) in);
        } else {
            return createFromTmpFile(in);
        }
    }

    /**
     * Creates a reset/mark supported input stream with hidden close method from any inputStream. It should be used as a last resource,
     * since it creates a temporary file.
     * 
     * @param in InputStream
     * @return HiddenCloseInputStream
     */
    public static InputStream createFromTmpFile(InputStream in) {
        try {
            return new ResetableFileInputStream(IOUtils.copyToTempFile("dataDigester", "tmp", in));
        } catch (IOException e) {
            throw new DataDigesterException(DataDigesterMessages.UNABLE_TO_CREATE_TMP_FILE.create(), e);
        }

    }

    /**
     * @param input the {@link InputStream}
     */
    public static void cleanup(InputStream input) {
        if (input instanceof ResetableFileInputStream) {
            ((ResetableFileInputStream) input).delete();
        } else {
            try {
                input.close();
            } catch (IOException e) {
                // ignore exceptions
            }            
        }
    }

}
